#include "cppTutorShared_Ptr.h"

// trace log
#include "cppTutorLog.h"
extern CcppTutorLog Log;

using namespace std;

class CSharedPtrDemo;

void sharedPtr () {
    Log << "ENTER : sharedPtr ()" << endl;
    
    cout << "Creating a new shared_ptr 'up' of type int and assigning a value 10000 to it" << endl;
    shared_ptr <int> sp (new int (10000));
    cout << *sp << endl;

    cout << "Crteaing a new shared_ptr 'sp2' and moving the content of 'sp' to it" << endl;
    shared_ptr <int> sp2(sp);    
    
    cout << "Checking if 'sp' is NULL now" << endl;
    if (sp){
        cout << "in shared pointer 'sp' and 'sp2' both share the same location!!!" << endl;
    }
    else {
        cout << "OOPS !!!" << endl;
    }    

    cout << "Creating an object of a class now" << endl;
    shared_ptr <CSharedPtrDemo> sp3 (new CSharedPtrDemo ());
    sp3->m_getValue();
    
    cout << "using make_shared functionality" << endl;
    shared_ptr <CSharedPtrDemo> sp4 = make_shared <CSharedPtrDemo>();
    sp4->m_getValue ();
 
    cout << "using auto and make_shared functionality" << endl; 
    auto sp5 = make_shared <CSharedPtrDemo>();
    sp4->m_getValue ();

    // cout << "using allocate_shared functionality" << endl;
    // shared_ptr <CSharedPtrDemo> sp6 = allocate_shared <CSharedPtrDemo>(alloc, 999);
    // sp6->m_getValue ();
    
    cout << "\ncheck the 'trace.log' file for the constructor and destructor call" << endl;
    
    Log << "EXIT  : sharedPtr ()" << endl;
}

CSharedPtrDemo :: CSharedPtrDemo () : m_nTest (10) {
    Log << "ENTER : CSharedPtrDemo :: CSharedPtrDemo ()" << endl;
    Log << "EXIT  : CSharedPtrDemo :: CSharedPtrDemo ()" << endl;
}

CSharedPtrDemo :: CSharedPtrDemo (int nTest) : m_nTest (nTest) {
    Log << "ENTER : CSharedPtrDemo :: CSharedPtrDemo ()" << endl;
    Log << "EXIT  : CSharedPtrDemo :: CSharedPtrDemo ()" << endl;
}

CSharedPtrDemo :: ~CSharedPtrDemo (){
    Log << "ENTER : CSharedPtrDemo :: ~CSharedPtrDemo ()" << endl;
    Log << "EXIT  : CSharedPtrDemo :: ~CSharedPtrDemo ()" << endl;
}

void CSharedPtrDemo :: m_getValue () {
    Log << "ENTER : CSharedPtrDemo :: m_getValue ()" << endl;
    cout << "checking the private data member with the object created : " << m_nTest << endl;
    Log << "EXIT  : CSharedPtrDemo :: m_getValue ()" << endl;
}